Imports System.ComponentModel
'todo: don't close all forms if just edit options tab
Public Class frmPrefs
    Inherits System.Windows.Forms.Form

    Shared Project As clsProject

    Private Class clsGraphicFileEditor : Inherits System.Windows.Forms.Design.FileNameEditor
        Protected Overrides Sub InitializeDialog(ByVal openFileDialog As System.Windows.Forms.OpenFileDialog)
            MyBase.InitializeDialog(openFileDialog)
            With openFileDialog
                .AddExtension = True
                .CheckFileExists = True
                .DefaultExt = "bmp"
                .Filter = "All Image Files (*.bmp,*.gif,*.jpg,*.jpeg,*.png,*.ico,*.emf,*.wmf)|*.bmp;*.gif;*.jpg;*.jpeg;*.png;*.ico;*.emf;*.wmf"
                If String.IsNullOrEmpty(Project.DesktopGraphicFile) Then
                    .InitialDirectory = AppDataPath
                Else
                    .InitialDirectory = IO.Path.GetDirectoryName(Project.DesktopGraphicFile)
                End If
                .FileName = Project.DesktopGraphicFile
            End With
        End Sub
    End Class

    Private Class clsGisFileEditor : Inherits System.Windows.Forms.Design.FileNameEditor
        Protected Overrides Sub InitializeDialog(ByVal openFileDialog As System.Windows.Forms.OpenFileDialog)
            MyBase.InitializeDialog(openFileDialog)
            With openFileDialog
                .AddExtension = True
                .CheckFileExists = True
                .DefaultExt = "gis"
                .Filter = "GIS Files (*.gis)|*.gis"
                If String.IsNullOrEmpty(Project.GisBasemapStations) Then
                    .InitialDirectory = AppDataPath
                Else
                    .InitialDirectory = IO.Path.GetDirectoryName(Project.GisBasemapStations)
                End If
            End With
        End Sub
    End Class

    Private Class clsFolderEditor : Inherits System.Windows.Forms.Design.FolderNameEditor
        Protected Overrides Sub InitializeDialog(ByVal FolderDialog As System.Windows.Forms.Design.FolderNameEditor.FolderBrowser)
            MyBase.InitializeDialog(FolderDialog)
            With FolderDialog
                .Style = FolderBrowserStyles.RestrictToFilesystem
                .StartLocation = FolderBrowserFolder.MyComputer
            End With
        End Sub
    End Class

    Private Class clsSQLFolderEditor : Inherits System.Windows.Forms.Design.FolderNameEditor
        Protected Overrides Sub InitializeDialog(ByVal FolderDialog As System.Windows.Forms.Design.FolderNameEditor.FolderBrowser)
            MyBase.InitializeDialog(FolderDialog)
            With FolderDialog
                .Style = FolderBrowserStyles.RestrictToFilesystem
                .StartLocation = FolderBrowserFolder.MyComputer

                .Description = "Select folder where SQL queries will be saved for this project."
            End With
        End Sub
    End Class

    Private Class clsUpdateFolderEditor : Inherits System.Windows.Forms.Design.FolderNameEditor
        Protected Overrides Sub InitializeDialog(ByVal FolderDialog As System.Windows.Forms.Design.FolderNameEditor.FolderBrowser)
            MyBase.InitializeDialog(FolderDialog)
            With FolderDialog
                '.Style = FolderBrowserStyles.ShowTextBox Or FolderBrowserStyles.RestrictToDomain
                .StartLocation = FolderBrowserFolder.MyComputer
                .Description = "Select network folder where WRDB updates reside; if updates are hosted on an Internet server, cancel this dialog and type the URL."
            End With
        End Sub
    End Class

    <DefaultProperty("Description")> _
    Private Class clsOptions

        <Editor(GetType(clsGraphicFileEditor), GetType(System.Drawing.Design.UITypeEditor)), _
        DisplayName("Desktop Graphic File"), Category("1. Project Settings"), _
        Description("This is the name of the graphic file that will be displayed as the desktop background. Click the ... button to browse.")> _
        Public Property DesktopGraphic() As String
            Get
                Return Project.DesktopGraphicFile
            End Get
            Set(ByVal value As String)
                Project.DesktopGraphicFile = value
            End Set
        End Property

        <DisplayName("Desktop Color Scheme"), Category("1. Project Settings"), _
        Description("This is the name of the color scheme to use for the desktop background.")> _
        Public Property DesktopColorScheme() As Project.clsProject.enumDesktopColorTheme
            Get
                Return Project.DesktopColorTheme
            End Get
            Set(ByVal value As Project.clsProject.enumDesktopColorTheme)
                Project.DesktopColorTheme = value
            End Set
        End Property

        <DisplayName("Description"), Category("1. Project Settings"), _
        Description("Description for project.")> _
        Public Property Description() As String
            Get
                Return Project.Description
            End Get
            Set(ByVal value As String)
                Project.Description = value
            End Set
        End Property

        <DisplayName("Title Bar Text"), Category("1. Project Settings"), _
        Description("Text to display on the WRDB title bar when this project is loaded. If blank, defaults to project name.")> _
        Public Property TitleBarText() As String
            Get
                Return Project.TitlebarText
            End Get
            Set(ByVal value As String)
                Project.TitlebarText = value
            End Set
        End Property

        '<DisplayName("Auto-refresh Record Counts?"), Category("1. Project Settings"), _
        'Description("Controls whether the number of table records are queried and displayed when opening Working tables (which can be time-consuming). If NotSet, will prompt you the first time that lengthy query occurs.")> _
        'Public Property DisplayRecordCount() As clsProject.enumDisplayRecordCount
        '    Get
        '        Return Project.DisplayRecordCount
        '    End Get
        '    Set(ByVal value As clsProject.enumDisplayRecordCount)
        '        Project.DisplayRecordCount = value
        '    End Set
        'End Property

        <DisplayName("Select records into..."), Category("1. Project Settings"), _
        Description("Select 'View' for very fast queries, but which result in slow subsequent operations (e.g., reports & graphs); select 'Table' to store query results in temporary table which will take longer, but make subsequent opertions much faster.")> _
        Public Property QueryOptions() As clsProject.enumQueryOption
            Get
                Return Project.QueryOption
            End Get
            Set(ByVal value As clsProject.enumQueryOption)
                Project.QueryOption = value
            End Set
        End Property

        <Editor(GetType(clsSQLFolderEditor), GetType(System.Drawing.Design.UITypeEditor)), _
         DisplayName("Saved Query Folder"), Category("1. Project Settings"), _
        Description("This is file path where WRDB will save and load Saved Queries.")> _
        Public Property SQLDir() As String
            Get
                Return RelativePath(Project.SQLDir)
            End Get
            Set(ByVal value As String)
                Project.SQLDir = AbsolutePath(value)
            End Set
        End Property

        <DisplayName("Display Advanced Menus?"), Category("1. Project Settings"), _
        Description("When true, non-Supervisor users can still see many advanced menu and toolbar items. Set to false to simplify the user interface.")> _
        Public Property AdvancedMenusVisible() As Boolean
            Get
                Return Project.AdvancedMenusVisible
            End Get
            Set(ByVal value As Boolean)
                Project.AdvancedMenusVisible = value
            End Set
        End Property

        <DisplayName("Read-Only Project?"), Category("1. Project Settings"), _
        Description("When true, in addition to normal restrictions, non-Supervisor users are also prevented from creating, editing, and adding to Working tables.")> _
        Public Property IsReadOnly() As Boolean
            Get
                Return Project.IsReadOnly
            End Get
            Set(ByVal value As Boolean)
                Project.IsReadOnly = value
            End Set
        End Property

        <DisplayName("WQX Displayed?"), Category("1. Project Settings"), _
        Description("When true, you will also have the ability to configure EPA's WQX (Water Quality Exchange) fields contained in the PCodes Support table.")> _
        Public Property WQXVisible() As Boolean
            Get
                Return Project.WQXVisible
            End Get
            Set(ByVal value As Boolean)
                Project.WQXVisible = value
            End Set
        End Property

        <DisplayName("Expert Mode?"), Category("2. Application Settings"), _
        Description("When true, some messages and prompts are suppressed and placed in status bar instead.")> _
        Public Property ExpertMode() As Boolean
            Get
                Return MainWRDB.ExpertMode
            End Get
            Set(ByVal value As Boolean)
                MainWRDB.ExpertMode = value
            End Set
        End Property

        <DisplayName("Grid Font"), Category("2. Application Settings"), _
        Description("Specify the font to use within data grids (browsers, reports, etc.).")> _
        Public Property GridFont() As Font
            Get
                Return MainWRDB.GridFont
            End Get
            Set(ByVal value As Font)
                MainWRDB.GridFont = value
            End Set
        End Property

        <DisplayName("Display Welcome Screen on Startup?"), Category("2. Application Settings"), _
        Description("When true, the 'Welcome to WRDB' startup dialog is displayed every time you start WRDB (does not apply to WRDB run from MapWindow). This allows you to select the initial Project and table.")> _
        Public Property DisplayStartup() As Boolean
            Get
                Return MainWRDB.ShowStartup
            End Get
            Set(ByVal value As Boolean)
                MainWRDB.ShowStartup = value
            End Set
        End Property

        <DisplayName("Display New Project Screen When Switching Projects?"), Category("2. Application Settings"), _
        Description("When true, the 'New Project' dialog is displayed every time you select a new project (does not apply to WRDB run from MapWindow). This displays relavent Project information and allows you to select from a set of common tasks.")> _
        Public Property DisplayNewProject() As Boolean
            Get
                Return MainWRDB.ShowNewProject
            End Get
            Set(ByVal value As Boolean)
                MainWRDB.ShowNewProject = value
            End Set
        End Property

        <DisplayName("Display Getting Started Form?"), Category("2. Application Settings"), _
        Description("When true, the 'Getting Started' form is displayed every time you start WRDB (application setting). This displays helpful WRDB fundamentals for the first-time user.")> _
        Public Property DisplayGettingStarted() As Boolean
            Get
                Return MainWRDB.ShowGettingStarted
            End Get
            Set(ByVal value As Boolean)
                MainWRDB.ShowGettingStarted = value
            End Set
        End Property

        <DisplayName("Auto-check for New Versions?"), Category("3. Program Updates"), _
        Description("When true, every time WRDB starts the WRDB web site (or alternate location indicated below) will be checked to see if new versions of the program or data provider libraries are available; if so you will be given the chance to download and update the required files.")> _
        Public Property CheckVersions() As Boolean
            Get
                Return MainWRDB.CheckUpdates
            End Get
            Set(ByVal value As Boolean)
                MainWRDB.CheckUpdates = value
            End Set
        End Property

        <Editor(GetType(clsUpdateFolderEditor), GetType(System.Drawing.Design.UITypeEditor)), _
         DisplayName("Update Repository"), Category("3. Program Updates"), _
        Description("This is the URL or file path where WRDB will check for new versions. By default it is 'http://www.wrdb.com/download/wrdb5/' but may be changed to a local share to speed the distribution of updates across an organization.")> _
        Public Property VersionRepository() As String
            Get
                Return MainWRDB.UpdateLocation
            End Get
            Set(ByVal value As String)
                MainWRDB.UpdateLocation = value
            End Set
        End Property

        '<DisplayName("Proxy Address"), Category("3. Program Updates"), _
        'Description("This is the address of the proxy server and port used to access the Internet. If you do not have one (or know what that is), just leave it blank. The proxy server address should have the form: myproxy:port where myproxy is the proxy address (prefixed by http:// if appropriate) and port is the port number. See your network administrator for assistance.")> _
        'Public Property ProxyServer() As String
        '    Get
        '        Return MainWRDB.ProxyAddress
        '    End Get
        '    Set(ByVal value As String)
        '        MainWRDB.ProxyAddress = value
        '        If Not value.Contains(":") Then WarningMsg("The proxy server address should have the form: myproxy:port where myproxy is the proxy address (prefixed by http:// if appropriate) and port is the port number. See your network administrator for assistance.")
        '    End Set
        'End Property

        '<DisplayName("Proxy User Name"), Category("3. Program Updates"), _
        'Description("This is the user name needed to log onto the proxy server which is used to access the Internet. If you use a proxy server but use 'NT Authentication' (i.e., automatic logon), just leave it blank. See your network administrator for assistance.")> _
        'Public Property ProxyUserName() As String
        '    Get
        '        Return MainWRDB.ProxyUserName
        '    End Get
        '    Set(ByVal value As String)
        '        MainWRDB.ProxyUserName = value
        '    End Set
        'End Property

        '<DisplayName("Proxy Password"), Category("3. Program Updates"), _
        'Description("This is the password needed to log onto the proxy server which is used to access the Internet. If you use a proxy server but use 'NT Authentication' (i.e., automatic logon), just leave it blank. See your network administrator for assistance."), _
        'PasswordPropertyText(True)> _
        'Public Property ProxyPassword() As String
        '    Get
        '        Return MainWRDB.ProxyPassword
        '    End Get
        '    Set(ByVal value As String)
        '        MainWRDB.ProxyPassword = value
        '    End Set
        'End Property

        '<Editor(GetType(clsFolderEditor), GetType(System.Drawing.Design.UITypeEditor)), _
        'DisplayName("Project File Directory"), Category("2. Application Settings"), _
        'Description("This is the name of the directory where the WRDB.ini file is stored; it contains information about all active Projects. Click the ... button to browse.")> _
        'Public Property ProjectFolder() As String
        '    Get
        '        Return AppDataPath
        '    End Get
        '    Set(ByVal value As String)
        '        If WarningMsg("This will cause the current project to close and WRDB will switch to the WRDB.ini file found in the specified directory (if present). Are you sure you want to continue?") = Windows.Forms.DialogResult.Cancel Then Exit Property
        '        ProjectMustClose = True
        '        AppDataPath = value
        '        DatabaseHasChanged = True
        '    End Set
        'End Property

        <DisplayName("Prompt When Importing?"), Category("4. Tracking"), _
        Description("When true, WRDB will prompt you to enter tracking information for each file or table you import (application setting).")> _
        Public Property PromptImport() As Boolean
            Get
                Return MainWRDB.PromptImport
            End Get
            Set(ByVal value As Boolean)
                MainWRDB.PromptImport = value
            End Set
        End Property

        <DisplayName("Default User Name for Tracking?"), Category("4. Tracking"), _
        Description("Specify the default user name to use when making Tracking table entries (defaults to login ID) (application setting).")> _
        Public Property UserName() As String
            Get
                Return MainWRDB.UserName
            End Get
            Set(ByVal value As String)
                MainWRDB.UserName = value
            End Set
        End Property

        <DisplayName("Report Heading Line 1"), Category("5. Reporting"), _
        Description("Specify line one of the report heading you want to appear at the top of printed reports; this is usually the agency name (application setting).")> _
        Public Property ReportHeading1() As String
            Get
                Return MainWRDB.ReportHeading1
            End Get
            Set(ByVal value As String)
                MainWRDB.ReportHeading1 = value
            End Set
        End Property

        <DisplayName("Report Heading Line 2"), Category("5. Reporting"), _
        Description("Specify line two of the report heading you want to appear at the top of printed reports; this is usually the agency location (application setting).")> _
        Public Property ReportHeading2() As String
            Get
                Return MainWRDB.ReportHeading2
            End Get
            Set(ByVal value As String)
                MainWRDB.ReportHeading2 = value
            End Set
        End Property

        <DisplayName("Report Scaling"), Category("5. Reporting"), _
        Description("Specify the report scaling option; this determines how wide reports are scaled to fit on the printed page (application setting).")> _
        Public Property ReportScaling() As clsWRDB.enumReportScaling
            Get
                Return MainWRDB.ReportScaling
            End Get
            Set(ByVal value As clsWRDB.enumReportScaling)
                MainWRDB.ReportScaling = value
            End Set
        End Property

        <DisplayName("Report Language"), Category("5. Reporting"), _
        Description("Specify the report language option; this determines the language used for report headings, footers, etc. (application setting).")> _
        Public Property ReportLanguage() As clsWRDB.enumReportLanguage
            Get
                Return MainWRDB.ReportLanguage
            End Get
            Set(ByVal value As clsWRDB.enumReportLanguage)
                MainWRDB.ReportLanguage = value
            End Set
        End Property

        <DisplayName("RCodes in Date-Time Report?"), Category("5. Reporting"), _
        Description("Do you want RCode values to be prepended to numeric results in the Sort By Date-Time crosstab report?")> _
        Public Property DateTimeRCodes() As Boolean
            Get
                Return Project.RptDateTimeRCode
            End Get
            Set(ByVal value As Boolean)
                Project.RptDateTimeRCode = value
            End Set
        End Property

        <DisplayName("Aggregate Times in Date-Time Report?"), Category("5. Reporting"), _
        Description("Do you want to combine all readings on a given date in the Sort By Date-Time crosstab report (ignoring times)?")> _
        Public Property DateTimeDate() As Boolean
            Get
                Return Project.RptDateTimeDate
            End Get
            Set(ByVal value As Boolean)
                Project.RptDateTimeDate = value
            End Set
        End Property

        <DisplayName("Quick PCode/CCode List Refresh?"), Category("6. BASINS and GIS"), _
        Description("If True, when data tables are opened the PCode (and CCode) drop-down lists are populated with all values from the Support tables; otherwise will query data table for unique values (which can take a long time for large tables).")> _
        Public Property GisQuickList() As Boolean
            Get
                Return Project.GisQuickList
            End Get
            Set(ByVal value As Boolean)
                Project.GisQuickList = value
            End Set
        End Property

        <DisplayName("Quick Attribute Table?"), Category("6. BASINS and GIS"), _
        Description("If True, when the WRDB Stations layer is created the associated attribute table will contain only the Station ID, name, and type; otherwise will contain all data in Stations table (which can take a long time for large tables).")> _
        Public Property GisQuickTable() As Boolean
            Get
                Return Project.GisQuickTable
            End Get
            Set(ByVal value As Boolean)
                Project.GisQuickTable = value
            End Set
        End Property

        <Editor(GetType(clsUpdateFolderEditor), GetType(System.Drawing.Design.UITypeEditor)), _
        DisplayName("GIS Directory"), Category("6. BASINS and GIS"), _
        Description("If non-blank, is directory where WRDB Stations shape file will be permanently retained; otherwise will be recreated in temporary directory each session (which can take a long time for large tables).")> _
        Public Property GisDirectory() As String
            Get
                Return Project.GisDirectory
            End Get
            Set(ByVal value As String)
                Project.GisDirectory = value
            End Set
        End Property

        <Editor(GetType(clsGisFileEditor), GetType(System.Drawing.Design.UITypeEditor)), _
        DisplayName("Basemap-Stations"), Category("6. BASINS and GIS"), _
        Description("If non-blank, is basemap which will be automatically loaded in WRDB GIS tool when displaying station locations or selecting stations.")> _
        Public Property GisBasemapStations() As String
            Get
                Return Project.GisBasemapStations
            End Get
            Set(ByVal value As String)
                Project.GisBasemapStations = value
            End Set
        End Property

        <Editor(GetType(clsGisFileEditor), GetType(System.Drawing.Design.UITypeEditor)), _
        DisplayName("Basemap-Output"), Category("6. BASINS and GIS"), _
        Description("If non-blank, is basemap which will be automatically loaded in WRDB GIS tool when displaying thematic map of selected data.")> _
        Public Property GisBasemapOutput() As String
            Get
                Return Project.GisBasemapOutput
            End Get
            Set(ByVal value As String)
                Project.GisBasemapOutput = value
            End Set
        End Property

    End Class

    Private Options As clsOptions
    Private LastBrowseDir As String = ""
    Shared DatabaseHasChanged As Boolean = False
    Shared ProjectMustClose As Boolean = False

    Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
        Try
            If DatabaseHasChanged Or ProjectMustClose Then
                With MainForm
                    For Each child As Form In .MdiChildren
                        child.Close()
                    Next
                End With
            End If

            If ProjectMustClose Then
                SaveSetting(REGAPP, "General", "AppDataPath", AppDataPath)
                MainWRDB = New wrdb.lib.clsWRDB
                DialogResult = Windows.Forms.DialogResult.OK
                Exit Sub
            End If

            IniFile.Save() 'will reopen in SetProject after clsProject updates it

            With Project
                If String.IsNullOrEmpty(txtDataSource.Text) Then
                    WarningMsg("You must specify a valid name for the database server or file.")
                    Exit Sub
                End If

                If Not TestConnection() Then Exit Sub
                .MasterTableName = Me.cboMasterTable.Text

                If Not .ResetPDox(clsProject.enumTableTypes.Master, True) Then Exit Sub

                If .MasterTableName.Trim = "" AndAlso MessageBox.Show("No Master table has been specified for this project; do you want to create a new Master table now?", "Select/Create Master Table", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.OK Then
                    btnCreateMaster.PerformClick()
                End If

                If .MasterTableName.Trim = "" Then
                    WarningMsg("You must select an existing or create a new Master table before proceeding.")
                    Exit Sub
                End If

                If .MasterTableName <> "" AndAlso Not .DB.TableExists(.MasterTableName) Then
                    If MessageBox.Show(String.Format("Master Table {0} was not found. Do you want to create it?", .MasterTableName), "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) = Windows.Forms.DialogResult.Yes Then
                        If HasTablePermissions(Project.DB) Then .CreateTable(clsProject.enumTableTypes.Master)
                    End If
                End If

                .Password = txtProjectPassword.Text.Trim

                .SavePreferences()
                IniFile.Reopen()
                SetProject(.Name, Not DatabaseHasChanged)
                If Not MainForm.CheckSupportTablesExist() Then Exit Sub

                'Project.DB.Dispose()
                Project = Nothing
                DialogResult = Windows.Forms.DialogResult.OK

            End With
        Catch ex As DbSqlException
            WarningMsg(ex.Message)
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTest.Click
        If TestConnection() Then
            MessageBox.Show("Successfully connected to database.", "Test Connection", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            MessageBox.Show("Unable to connect to database.", "Test Connection", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If
    End Sub

    Private Function TestConnection() As Boolean
        Try
            With Project
                MainForm.WriteProgress("Connecting to database...", ProgressBarStyle.Marquee)

                Dim DataSource As String = txtDataSource.Text
                Dim DatabaseName As String = txtDatabaseName.Text

                Dim Ext As String

                Select Case SelectedDatabaseType()
                    Case clsDB.enumDBType.Access : Ext = ".mdb"
                    Case clsDB.enumDBType.Firebird_Embedded : Ext = ".fdb"
                    Case clsDB.enumDBType.SQLite : Ext = ".sdb"
                    Case clsDB.enumDBType.SQL_Server_CE : Ext = ".sdf"
                    Case Else
                        Ext = ""
                End Select

                Select Case SelectedDatabaseType()
                    Case clsDB.enumDBType.Access, clsDB.enumDBType.Firebird_Embedded, clsDB.enumDBType.SQLite, clsDB.enumDBType.DBase, clsDB.enumDBType.SQL_Server_CE
                        DataSource = AbsolutePath(DataSource, Ext)
                    Case clsDB.enumDBType.Firebird
                        'database files will be stored on server in the root directory, and given the extension fdb
                        DatabaseName = String.Format("\{0}.fdb", DatabaseName)
                End Select

                Try
                    .DB = clsDB.GetDataProvider(SelectedDatabaseType, DataSource, DatabaseName, txtUserName.Text, txtPswd.Text, Val(txtTimeout.Text))
                    If .DB Is Nothing Then Return False
                Catch ex As DbSqlException
                    ErrorMsg("Unable to connect to database.", ex)
                    Return False
                Catch ex As Exception
                    'CE returns error if no file exists when just create connection; give it a change to create it below
                    'If .DB.DatabaseType <> clsDB.enumDBType.SQL_Server_CE Then Return False
                    Return False
                End Try

                'make sure database exists & offer to create

                If Not .DB.TestConnection Then
                    MainForm.ProgressComplete()

                    Select Case .DB.DatabaseType
                        Case clsDB.enumDBType.Access, clsDB.enumDBType.Firebird_Embedded, clsDB.enumDBType.SQLite, clsDB.enumDBType.SQL_Server_CE
                            If MessageBox.Show(String.Format("Database {0} was not found. Do you want to create it?", .DB.DataSource), "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) = Windows.Forms.DialogResult.No Then Return False
                            Select Case .DB.DatabaseType
                                Case clsDB.enumDBType.Access, clsDB.enumDBType.SQLite, clsDB.enumDBType.SQL_Server_CE
                                    If Not String.IsNullOrEmpty(txtPswd.Text) Then
                                        Dim frm As New frmLogin
                                        frm.lblInfo.Text = "Once this database file is created with the specified password, you will not be able to access the data without resupplying it. To make sure that you have entered it correctly, please reenter it again below (and then store the password in a safe place)."
                                        If frm.ShowDialog(Me) = Windows.Forms.DialogResult.Cancel OrElse frm.txtPassword.Text <> txtPswd.Text Then Return False
                                        frm.Dispose()
                                    End If
                            End Select
                            If Not .DB.CreateDatabase(.DB.DataSource) Then Return False
                            txtDataSource.Text = RelativePath(.DB.DataSource) 'name may have changed

                        Case clsDB.enumDBType.DBase
                            If Not .DB.DataSource.EndsWith("\") Then .DB.DataSource &= "\"
                            If Not My.Computer.FileSystem.DirectoryExists(.DB.DataSource) Then
                                If MessageBox.Show("The directory you specified was not found. Do you want to create it?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) = Windows.Forms.DialogResult.Yes Then
                                    My.Computer.FileSystem.CreateDirectory(.DB.DataSource)
                                Else
                                    Return False
                                End If
                            End If

                        Case clsDB.enumDBType.SQL_Server, clsDB.enumDBType.MySQL
                            If .DB.LastException IsNot Nothing Then
                                Throw .DB.LastException
                            End If
                            .DB = clsDB.GetDataProvider(SelectedDatabaseType, DataSource, IIf(.DB.DatabaseType = clsDB.enumDBType.SQL_Server, "master", "mysql"), txtUserName.Text, txtPswd.Text, txtTimeout.Text)
                            If .DB Is Nothing Then Return False
                            Try
                                .DB.OpenConnection()
                            Catch ex As DbSqlException
                                WarningMsg("Unable to connect to specified data provider database. Please check all connection and security settings.", , ex)
                                Return False
                            End Try
                            Dim dt As DataTable = .DB.Connection.GetSchema("DATABASES")

                            Dim found As Boolean = False
                            For Each dr As DataRow In dt.Rows
                                If dr("Database_Name").ToString.Equals(DatabaseName, StringComparison.OrdinalIgnoreCase) Then found = True : Exit For
                            Next
                            dt.Dispose()
                            dt = Nothing

                            If Not found AndAlso MessageBox.Show(String.Format("Database {0} was not found. Do you want to create it?", Me.txtDatabaseName.Text), "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) = Windows.Forms.DialogResult.Yes Then
                                .DB.DatabaseName = .DB.GetValidObjectName(DatabaseName)
                                If Not .DB.CreateDatabase(DatabaseName) Then Return False
                                txtDatabaseName.Text = DatabaseName
                            End If

                        Case clsDB.enumDBType.Oracle
                            Try
                                If .DB.Connection Is Nothing Then Return False 'do not allow user to create database (actually tablespace) because they are mapped to username by DBA
                                .DB.OpenConnection()
                            Catch ex As System.TypeInitializationException
                                WarningMsg("Unable to connect to Oracle because you do not have the necessary Oracle client libraries installed (these are not automatically installed by WRDB). Please download and install these client libraries before trying to access an Oracle database (or use a different database type). Note that you must also install Oracle Database Access Components (ODAC) libraries available from www.Oracle.com (search for 'download ODAC').", , ex)
                                Return False
                            Catch ex As DbSqlException
                                WarningMsg("Unable to connect to specified data provider database. Please check all connection and security settings.", , ex)
                                Return False
                            End Try

                        Case clsDB.enumDBType.Firebird
                            'GetSchema doesn't include any way to list databases on Firebird server; just try to connect and if error, offer to create
                            'note that dbname in Firebird is actually full path to the database file on the server; place all on root directory under WRDB
                            Try
                                .DB.OpenConnection()
                            Catch ex As DbSqlException
                                If MessageBox.Show(String.Format("Either the Firebird server couldn't be accessed or the database '{0}' was not found. Please check all connection and security settings. Do you want to attempt to create the specified database?", IO.Path.GetFileNameWithoutExtension(.DB.DatabaseName)), "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) = Windows.Forms.DialogResult.No Then Return False
                                If Not .DB.CreateDatabase(.DB.DatabaseName) Then
                                    WarningMsg("Unable to create database on Firebird server; this probably means that you cannot connect to the server or your security settings are incorrect.\n\nNOTE: WRDB assumes that the Firebird server is configured on this computer or another database server that you have access to it through your firewall. The physical database files will be saved on the Firebird server in the root directory of the same drive where Windows is installed and given the extension .FDB.")
                                    Return False
                                End If
                            End Try
                    End Select
                End If

                .DB.Connection.Close()
            End With

        Catch ex As DbSqlException
            WarningMsg(ex.Message)
            Return False
        Catch ex As Exception
            ErrorMsg(, ex)
            Return False
        Finally
            MainForm.ProgressComplete()
        End Try
        Return True
    End Function

    Private Sub cboDatabaseType_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboDatabaseType.SelectedIndexChanged
        tblConfig.SuspendLayout()
        Try
            With Project
                If cboDatabaseType.SelectedIndex = -1 Then Exit Sub

                'all the following may have been made invisible if creating a new project and no database type selected yet
                lblDataSource.Visible = True
                txtDataSource.Visible = True
                btnDataSource.Visible = True
                lblMasterTable.Visible = True
                cboMasterTable.Visible = True
                btnCreateMaster.Visible = True
                lblTimeout.Visible = True
                txtTimeout.Visible = True

                lblNotes.Visible = True
                btnTest.Visible = True

                If Not MainWRDB.DataProviderAvailable(SelectedDatabaseType) Then cboDatabaseType.SelectedIndex = -1

                Dim IsEmbedded As Boolean = SelectedDatabaseType() = clsDB.enumDBType.Access Or
                                            SelectedDatabaseType() = clsDB.enumDBType.Firebird_Embedded Or
                                            SelectedDatabaseType() = clsDB.enumDBType.SQLite Or
                                            SelectedDatabaseType() = clsDB.enumDBType.SQL_Server_CE

                Dim AllowsPswd As Boolean
                Select Case SelectedDatabaseType()
                    Case clsDB.enumDBType.Access, clsDB.enumDBType.Firebird, clsDB.enumDBType.MySQL, clsDB.enumDBType.Oracle, clsDB.enumDBType.SQL_Server, clsDB.enumDBType.SQLite, clsDB.enumDBType.SQL_Server_CE
                        AllowsPswd = True
                    Case Else
                        AllowsPswd = False
                End Select

                Dim AllowBrowse As Boolean = Not (SelectedDatabaseType() = clsDB.enumDBType.Firebird)
                lblNotes.Visible = True
                btnDataSource.Enabled = True

                If IsEmbedded Then
                    lblDataSource.Text = "&Database Name:" : If .DB IsNot Nothing Then txtDataSource.Text = RelativePath(.DB.DataSource)
                    lblNotes.Text = "Note: " & cboDatabaseType.Text & " tables are all stored inside a single database file." & IIf(AllowsPswd, " The Username and Password entries are optional and will normally not be used for this data provider.", "")
                Else
                    lblDataSource.Text = "&Server Name:" : If .DB IsNot Nothing Then txtDataSource.Text = .DB.DataSource
                    btnDataSource.Enabled = False
                    lblDatabaseName.Text = "&Database Name:" : If .DB IsNot Nothing Then txtDatabaseName.Text = .DB.DatabaseName
                    If SelectedDatabaseType() = clsDB.enumDBType.Firebird Then If .DB IsNot Nothing Then txtDatabaseName.Text = IO.Path.GetFileNameWithoutExtension(.DB.DatabaseName)
                    lblNotes.Visible = True
                    Dim port As Integer = 0
                    Dim info As String = ""
                    Select Case SelectedDatabaseType()
                        Case clsDB.enumDBType.Firebird : port = 3050 : info = " The .fdb database file MUST be stored in the root directory of the server."
                        Case clsDB.enumDBType.MySQL : port = 3306
                        Case clsDB.enumDBType.Oracle : port = 1521 : info = " The owner of all tables MUST be designated as 'WRDB'."
                        Case clsDB.enumDBType.SQL_Server : port = 1433
                    End Select
                    lblNotes.Text = String.Format("Note: this provider communicates with the database server using TCP/IP port number {0} by default. You may have to configure your computer (and workgroup's) firewall to allow traffic through this port.{1}", port, info)
                End If

                'note: Oracle employs tablespaces, rather than databases; these are mapped to a specific username
                'for now, do not allow tablespaces to be created by user (must be DBA)

                lblDatabaseName.Visible = Not (IsEmbedded Or SelectedDatabaseType() = clsDB.enumDBType.Oracle Or SelectedDatabaseType() = clsDB.enumDBType.DBase)
                txtDatabaseName.Visible = Not (IsEmbedded Or SelectedDatabaseType() = clsDB.enumDBType.Oracle Or SelectedDatabaseType() = clsDB.enumDBType.DBase)
                btnDatabaseName.Visible = Not (IsEmbedded Or SelectedDatabaseType() = clsDB.enumDBType.Oracle Or SelectedDatabaseType() = clsDB.enumDBType.DBase)

                If SelectedDatabaseType() = clsDB.enumDBType.SQL_Server Then
                    chkWindowsSecurity.Visible = True
                    chkWindowsSecurity.Checked = .DB Is Nothing OrElse .DB.UserName = ""
                Else
                    chkWindowsSecurity.Visible = False
                    chkWindowsSecurity.Checked = False
                    lblUserName.Visible = AllowsPswd And Not IsEmbedded
                    txtUserName.Visible = AllowsPswd And Not IsEmbedded
                    lblPswd.Visible = AllowsPswd
                    txtPswd.Visible = AllowsPswd
                End If
                If AllowsPswd And .DB IsNot Nothing Then
                    If SelectedDatabaseType() = clsDB.enumDBType.SQL_Server AndAlso String.IsNullOrEmpty(.DB.UserName) Then
                        chkWindowsSecurity.Checked = True
                    Else
                        txtUserName.Text = .DB.UserName
                        txtPswd.Text = .DB.Password
                    End If
                End If

                btnDatabaseName.Enabled = AllowBrowse

                If .DB Is Nothing Then txtTimeout.Text = 30 Else txtTimeout.Text = .DB.CommandTimeout

                If .Password = "Not Set" Then txtProjectPassword.Text = "" Else txtProjectPassword.Text = .Password
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        Finally
            tblConfig.ResumeLayout(True)
        End Try
    End Sub

    Private Sub btnBrowse_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDataSource.Click, btnDatabaseName.Click
        Dim txt As TextBox = Nothing
        Select Case CType(sender, Control).Name
            Case btnDataSource.Name : txt = txtDataSource
            Case btnDatabaseName.Name : txt = txtDatabaseName
        End Select
        GetDatabase(txt)
        Select Case SelectedDatabaseType()
            Case clsDB.enumDBType.Access, clsDB.enumDBType.Firebird_Embedded, clsDB.enumDBType.SQLite, clsDB.enumDBType.SQL_Server_CE
                Project.SQLDir = IO.Path.GetDirectoryName(AbsolutePath(txtDataSource.Text))
        End Select
    End Sub

    Private Function SelectedDatabaseType() As clsDB.enumDBType
        Return [Enum].Parse(GetType(clsDB.enumDBType), cboDatabaseType.Text.Replace(" ", "_"))
    End Function

    Private Sub GetDatabase(ByRef txt As TextBox)
        Try
            Dim Ext, Filter As String

            If SelectedDatabaseType() = clsDB.enumDBType.Access Then
                Ext = ".mdb"
                Filter = "Microsoft Access Database (*.mdb)|*.mdb"
            ElseIf SelectedDatabaseType() = clsDB.enumDBType.SQL_Server_CE Then
                Ext = ".sdf"
                Filter = "SQL Server CE Database (*.sdf)|*.sdf"
            ElseIf SelectedDatabaseType() = clsDB.enumDBType.Firebird_Embedded Then
                Ext = ".fdb"
                Filter = "Firebird Database (*.fdb)|*.fdb"
            ElseIf SelectedDatabaseType() = clsDB.enumDBType.SQLite Then
                Ext = ".sdb"
                Filter = "SQLite 3 Database (*.sdb)|*.sdb"
            Else
                Ext = ""
                Filter = ""
            End If
            Filter &= "|All Files (*.*)|*.*"

            Select Case SelectedDatabaseType()
                Case clsDB.enumDBType.Access, clsDB.enumDBType.Firebird_Embedded, clsDB.enumDBType.SQLite, clsDB.enumDBType.SQL_Server_CE
                    With New OpenFileDialog
                        .AddExtension = True
                        .CheckPathExists = True
                        .CheckFileExists = False
                        .DefaultExt = Ext
                        .Filter = Filter

                        Dim InitDir As String = AbsolutePath(txt.Text)
                        If IO.Directory.Exists(InitDir) Then
                            .InitialDirectory = IO.Path.GetDirectoryName(InitDir)
                        Else
                            .InitialDirectory = AppDataPath
                            If Not My.Computer.FileSystem.DirectoryExists(.InitialDirectory) Then My.Computer.FileSystem.CreateDirectory(.InitialDirectory)
                        End If
                        If .ShowDialog(Me) = Windows.Forms.DialogResult.OK Then txt.Text = RelativePath(.FileName)
                    End With
                Case clsDB.enumDBType.SQL_Server, clsDB.enumDBType.MySQL
                    Dim DatabaseList As New Generic.List(Of String)
                    With Project
                        .DB = clsDB.GetDataProvider(SelectedDatabaseType, Me.txtDataSource.Text, IIf(SelectedDatabaseType() = clsDB.enumDBType.SQL_Server, "master", "mysql"), txtUserName.Text, txtPswd.Text, txtTimeout.Text)
                        If .DB IsNot Nothing AndAlso .DB.OpenConnection Then
                            Dim dt As DataTable = .DB.Connection.GetSchema("DATABASES")
                            Dim found As Boolean = False
                            For Each dr As DataRow In dt.Rows
                                DatabaseList.Add(dr("Database_Name").ToString)
                            Next
                            DatabaseList.Sort()
                            dt.Dispose()
                            dt = Nothing
                            .DB.Connection.Close()
                            With New frmSelect(False)
                                .lstItems.Items.AddRange(DatabaseList.ToArray)
                                If .ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                                    txt.Text = .lstItems.Text
                                End If
                                .Dispose()
                            End With
                        End If
                    End With
                Case Else
                    lblInfo.Visible = True
                    tblConfig.Visible = False
                    Dim s As String = GetConnectString()
                    lblInfo.Visible = False
                    tblConfig.Visible = True

                    If s = "" Then Exit Sub

                    Dim ar() As String = s.Split(";")
                    Me.txtPswd.UseSystemPasswordChar = False
                    Me.txtPswd.PasswordChar = ""
                    Me.txtPswd.Text = "?Enter Password Here?"
                    For i As Int16 = 0 To UBound(ar)
                        If ar(i).StartsWith("DATA SOURCE", StringComparison.OrdinalIgnoreCase) Then
                            txtDataSource.Text = ar(i).Split("=")(1).Trim
                        ElseIf ar(i).StartsWith("INITIAL CATALOG", StringComparison.OrdinalIgnoreCase) Then
                            txtDatabaseName.Text = ar(i).Split("=")(1).Trim
                        ElseIf ar(i).StartsWith("USER ID", StringComparison.OrdinalIgnoreCase) Then
                            txtUserName.Text = ar(i).Split("=")(1).Trim
                        ElseIf ar(i).StartsWith("PASSWORD", StringComparison.OrdinalIgnoreCase) Then
                            txtPswd.Text = ar(i).Split("=")(1).Trim
                        End If
                    Next
            End Select
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Function GetConnectString() As String
        'Purpose of Function: Build a Connection String
        'References required: oledb32.dll (MS Ole DB Service component)
        'Returns a standard connection string
        Try
            Dim varDataLink As New MSDASC.DataLinks
            Dim oConn As Object = varDataLink.PromptNew()
            If oConn Is Nothing Then Return "" Else Return oConn.ConnectionString
        Catch ex As Exception
            ErrorMsg("Unable to build connection string.", ex)
            Return Nothing
        End Try
    End Function

    Private Sub frmPrefs_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        SaveWindowPos(REGAPP, Me)
    End Sub

    Private Sub frmPrefs_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        GetWindowPos(REGAPP, Me)

        ReplaceTooltipAndHelpText(Me, Me.ToolTip1, Me.HelpProvider1)
        If modWRDB.Project Is Nothing Then
            Project = New clsProject
        Else
            Project = modWRDB.Project.Clone
        End If
        ProjectMustClose = False
        With Project
            Text = "Project Preferences: " & .Name
            With cboDatabaseType
                .Items.Clear()
                'Dim AvailTypes As Generic.List(Of clsDB.enumDBType) = clsDB.EnumDataProviders()
                'note: do not include support for dbase tables because they have 10-character limitation on field names (violated by RCodes and Branches) and limitation on creation of primary key
                For dbType As clsDB.enumDBType = clsDB.enumDBType.Access To clsDB.enumDBType.SQLite
                    Dim dbTypeName As String = dbType.ToString.Replace("_", " ")
                    .Items.Add(dbTypeName)
                Next
            End With
            If .DB Is Nothing Then
                cboDatabaseType.SelectedIndex = -1
                'hide all other controls
                For Each cntl As Control In tblConfig.Controls
                    If Not cntl.Name.EndsWith("DatabaseType") Then cntl.Visible = False
                Next
                lblNotes.Visible = True
                lblNotes.Text = "Select the database type (data provider) you wish to use for this new project (the online help manual describes the merits of each data provider). Then enter the required information for the database."
            Else
                cboDatabaseType.Text = [Enum].GetName(GetType(clsDB.enumDBType), .DB.DatabaseType).Replace("_", " ")
            End If
            cboMasterTable.Text = .MasterTableName
            cboMasterTable.MaxLength = Project.dsWRDB.Tables("TRACKING").Columns("MASTER_DB_NAME").MaxLength
            Options = New clsOptions
            pgOptions.SelectedObject = Options
            pgOptions.ToolbarVisible = False
            DatabaseHasChanged = False
        End With
    End Sub

    Private Sub txt_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtDatabaseName.TextChanged, txtDataSource.TextChanged, txtUserName.TextChanged
        With CType(sender, TextBox)
            ToolTip1.SetToolTip(sender, .Text)
        End With
        DatabaseHasChanged = True
    End Sub

    Private Sub cboDatabaseType_SelectionChangeCommitted(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboDatabaseType.SelectionChangeCommitted
        Me.txtDatabaseName.Clear()
        Me.txtDataSource.Clear()
        Me.cboMasterTable.SelectedIndex = -1
        Me.txtPswd.Clear()
        Me.txtUserName.Clear()
    End Sub

    Private Sub txtDataSource_Validated(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtDataSource.Validated
        Select Case SelectedDatabaseType()
            Case clsDB.enumDBType.Access, clsDB.enumDBType.Firebird_Embedded, clsDB.enumDBType.SQLite, clsDB.enumDBType.SQL_Server_CE
                Project.SQLDir = IO.Path.GetDirectoryName(AbsolutePath(txtDataSource.Text))
        End Select
    End Sub

    Private Sub cboMasterTable_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboMasterTable.DropDown
        cboMasterTable.Items.Clear()
        With Project
            If TestConnection() Then
                Dim MasterTableList As New Generic.List(Of String)
                .ResetPDox(clsProject.enumTableTypes.Master)
                For Each s As String In .GetTableList(clsProject.enumTableTypes.Working, clsProject.enumTableTypes.Master)
                    MasterTableList.Add(s)
                Next
                .DB.Connection.Close()
                Application.DoEvents()
                cboMasterTable.Items.AddRange(MasterTableList.ToArray)
                If MasterTableList.Count = 0 AndAlso MessageBox.Show("No data tables exist in this project; do you want to create a new Master table now?", "Select Master Table", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) = Windows.Forms.DialogResult.OK Then
                    btnCreateMaster.PerformClick()
                End If
            End If
        End With
    End Sub

    Private Sub lnkClearRecent_LinkClicked(sender As System.Object, e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles lnkClearRecent.LinkClicked
        With MainForm
            With .mruMenuProj
                .RemoveAll()
                .ClearRegistry()
            End With
            With .mruMenuTable
                .RemoveAll()
                .ClearRegistry()
            End With
        End With
        frmInfoMsg.ResetAllInfoMsgs()
    End Sub

    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        Close()
    End Sub

    Private Sub btnCreateMaster_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreateMaster.Click
        If Not (TestConnection() AndAlso HasTablePermissions(Project.DB)) Then Exit Sub

        Dim Master As String
        With Project
            Do
                Master = InputBox("Enter the name of the new Master table you wish to create:", "Create Master Table", IIf(cboMasterTable.Text = "", "Master", cboMasterTable.Text))
                If Master.Trim = "" Then Exit Sub

                If .DB.TableExists(Master) Then
                    If WarningMsg("That table already exists; either select it from the drop-down line or specify a different name.", , , True) = Windows.Forms.DialogResult.Cancel Then Exit Sub
                Else
                    Exit Do
                End If
            Loop
            Try
                Master = .DB.GetValidTableName(Master) : If Master = "" Then Exit Sub
                If .DB.CreateTable(Master, .dsWRDB.Tables(clsProject.enumTableTypes.Master), .DB.IsPrimaryKeyRequired) Then
                    .MasterTableName = Master
                    cboMasterTable.Text = Master
                End If
            Catch ex As DbSqlException
                WarningMsg(ex.Message)
            End Try
        End With
    End Sub

    ''' <summary>
    ''' Given a path or file, return the path relative to MyDocuments
    ''' </summary>
    Shared Function RelativePath(ByVal Path As String) As String
        Dim MyPath As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\WRDB\"
        If IO.Path.IsPathRooted(Path) AndAlso Path.StartsWith(MyPath, StringComparison.OrdinalIgnoreCase) AndAlso Not String.Equals(MyPath, Path, StringComparison.OrdinalIgnoreCase) Then
            Return Path.Substring(MyPath.Length)
        Else
            Return Path
        End If
    End Function

    ''' <summary>
    ''' Given a path or file possibly relative to MyDocuments, return the absolute path 
    ''' </summary>
    Shared Function AbsolutePath(ByVal Path As String, Optional ByVal Ext As String = "") As String
        Dim MyPath As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\WRDB"
        If Not IO.Path.IsPathRooted(Path) Then
            Return MyPath & "\" & Path & IIf(Ext <> "" AndAlso Path.EndsWith(Ext, StringComparison.OrdinalIgnoreCase), "", Ext)
        Else
            Return Path
        End If
    End Function

    Private Sub btnHelp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnHelp.Click
        ShowHelp(Me, "12")
    End Sub

    Private Sub txtProjectPassword_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles txtProjectPassword.Validating
        txtProjectPassword.Text = txtProjectPassword.Text.Trim
        If txtProjectPassword.Text <> "" Then
            With New frmLogin
                .lblInfo.Text = "Please reenter the password to confirm..."
                If .ShowDialog(MainForm) = DialogResult.OK Then
                    If String.Equals(Me.txtProjectPassword.Text.Trim, .txtPassword.Text.Trim, StringComparison.InvariantCultureIgnoreCase) Then
                        Project.Password = txtProjectPassword.Text
                        e.Cancel = False
                    Else
                        WarningMsg("The two passwords did not match!")
                        e.Cancel = True
                    End If
                Else
                    e.Cancel = True
                End If
            End With
        End If
    End Sub

    Private Sub frmPrefs_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
        Static AlreadyShown As Boolean = False
        If Not AlreadyShown Then frmInfoMsg.ShowInfoMsg("Project Preferences", "Project Preferences are used to indicate where database files are located and select a number of options that control the appearance and operation of WRDB.\n\nIf you want to provide a measure of security to your Project tables, enter a Project Password. This will require that you reenter the password to gain access to some potentially destructive features of WRDB. You can also set some preferences which will hide some advanced features and force the database to be read-only to non-Supervisor users.\n\nHint: to provide the highest security for password-protected data providers like Oracle and SQL Server, the Project Supervisor can configure the project, place the WRDB.ini file on a network share, and require that all users reference that file for data access. See the online help manual for more information.")
        AlreadyShown = True
    End Sub

    Private Sub chkWindowsSecurity_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkWindowsSecurity.CheckedChanged
        lblUserName.Visible = Not chkWindowsSecurity.Checked
        txtUserName.Visible = Not chkWindowsSecurity.Checked
        lblPswd.Visible = Not chkWindowsSecurity.Checked
        txtPswd.Visible = Not chkWindowsSecurity.Checked
        If chkWindowsSecurity.Checked Then
            txtUserName.Text = ""
            txtPswd.Text = ""
        End If
    End Sub
End Class
